package com.aplink.generic.xmlparser;

import android.content.Context;
import android.content.res.Resources;

import com.aplink.generic.constant.ConfigParameter;
import com.aplink.generic.constant.ControlType;
import com.aplink.generic.constant.EditTextType;
import com.aplink.generic.pojo.ObjPropInfo;
import com.aplink.generic.pojo.ObjectFilter;
import com.aplink.generic.pojo.controlspec.ButtonSpec;
import com.aplink.generic.pojo.controlspec.CheckBoxSpec;
import com.aplink.generic.pojo.controlspec.ControlSpec;
import com.aplink.generic.pojo.controlspec.EditTextSpec;
import com.aplink.generic.pojo.controlspec.GridViewSpec;
import com.aplink.generic.pojo.controlspec.GridViewSpec.GridViewItem;
import com.aplink.generic.pojo.controlspec.ListviewSpec;
import com.aplink.generic.pojo.controlspec.MenuSpec;
import com.aplink.generic.pojo.controlspec.PopupMenuSpec;
import com.aplink.generic.pojo.controlspec.PopupMenuSpec.PopupMenuItem;
import com.aplink.generic.pojo.controlspec.SpinnerSpec;
import com.aplink.generic.pojo.controlspec.TabHostSpec;
import com.aplink.generic.pojo.controlspec.TabHostSpec.TabItem;
import com.aplink.generic.pojo.controlspec.ViewPagerSpec;
import com.aplink.generic.pojo.controlspec.ViewPagerSpec.ViewPagerItem;
import com.aplink.generic.util.objectrule.ActionBaseRule;
import com.aplink.generic.util.objectrule.ActionCompareRule;
import com.aplink.generic.util.objectrule.ObjectBaseRule;
import com.aplink.generic.util.objectrule.ObjectLoadBaseRule;
import com.aplink.generic.util.objectrule.ObjectNotLoadBaseRule;
import com.aplink.generic.util.objectrule.TargetRule;
import com.aplink.generic.util.objectrule.TargetRuleCollection;
import com.aplink.generic.util.objectrule.ValueBaseRule;
import com.aplink.generic.util.objectrule.ValueContainRule;
import com.aplink.generic.util.objectrule.ValueEqualRule;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.util.ArrayList;

import javax.xml.parsers.ParserConfigurationException;

public class ControlSpecParser {
	
	private static ArrayList<ControlSpec> parse(Document doc, String tagName) {
		ArrayList<ControlSpec> controlSpecList = new ArrayList<ControlSpec>();
		NodeList nList = doc.getElementsByTagName(tagName);
		
		if (nList.getLength() == 0) {
			return null;
		}
		Node nNode = nList.item(0);
		
		if (nNode.getNodeType() == Node.ELEMENT_NODE) {
			
			Element element = (Element) nNode;
			NodeList nodes = element
					.getElementsByTagName(ConfigParameter.CONTROL_STYLE);
			if (nodes.getLength() == 0) {
				return null;
			}
			
			for (int temp = 0; temp < nodes.getLength(); temp++) {
				ControlSpec controlSpec = new ControlSpec();
				Node nControlNode = nodes.item(temp);
				String controlType = null;
				String controlId = null;
				boolean isSearch = false;
				String searchControl = null;
				String searchFields = null;
				String mappingName = null;
				String dataInputType = null;
				boolean isVisibility = true;
				int minLength = EditTextSpec.MIN_LENGTH;
				int maxLenght = EditTextSpec.MAX_LENGTH;
				String dataObject = null;
				boolean isAddBlankRow = false;
				boolean isChecked = false;
				String displayProperty = null;
				String valueProperty = null;
				String contentData = null;
				String rptrDesign = null;
				String rowItem = null;
				String selectWhere = null;
				boolean isNoBlank = false;
				boolean isReadOnly = false;
				boolean noDuplicate = false;
				String validationGroup = null;
				ObjectBaseRule objectBaseRule = null;
				String value = null;
				TargetRuleCollection targetRuleCollection = null;
				String mViewpagerHeaderStyle = null;
				int tabhostStartPageIndex = 0;
				String tabhostBackgroundColor = null;
				String tabhostDisplayStyle = null;
				boolean isViewPagerLoadByConfig = true;
				if (nControlNode.hasAttributes()) {
					// find attr ctltype
					controlType = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_TYPE);
					controlSpec.setControlType(controlType);
					controlId = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_ID);
					value = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_VALUE);
					isSearch = false;
					if (XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_ISSEARCH) != null) {
						String val = XMLPaserUtil.getAttrValue(nControlNode,
								ConfigParameter.CONTROL_ISSEARCH);
						if (val.compareToIgnoreCase("Y") == 0) {
							isSearch = true;
						}
					}
					searchControl = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_SEARCHCTRL);
					// find searchFields
					searchFields = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_SEARCHFIELDS);
					// find mapping name
					mappingName = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_MAPPINGNAME);
					// find inputType
					dataInputType = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_INPUTTYPE);
					// find Visibility Type
					if (XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_VISIBILITY) != null) {
						String val = XMLPaserUtil.getAttrValue(nControlNode,
								ConfigParameter.CONTROL_VISIBILITY);
						if (val.compareToIgnoreCase("N") == 0) {
							isVisibility = false;
						}
					}
					// find minLength
					minLength = EditTextSpec.MIN_LENGTH;
					if (XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_MINLENGTH) != null) {
						String val = XMLPaserUtil.getAttrValue(nControlNode,
								ConfigParameter.CONTROL_MINLENGTH);
						try {
							minLength = Integer.parseInt(val);
						} catch (NumberFormatException e) {
							minLength = EditTextSpec.MIN_LENGTH;
						}
					}
					// find maxLength
					maxLenght = EditTextSpec.MAX_LENGTH;
					if (XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_MAXLENGTH) != null) {
						String val = XMLPaserUtil.getAttrValue(nControlNode,
								ConfigParameter.CONTROL_MAXLENGTH);
						try {
							maxLenght = Integer.parseInt(val);
						} catch (NumberFormatException e) {
							maxLenght = EditTextSpec.MAX_LENGTH;
						}
					}
					// find dataobj
					dataObject = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_DATAOBJ);
					
					// find addblank
					isAddBlankRow = false;
					if (XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_ADDBLANKROW) != null) {
						String val = XMLPaserUtil.getAttrValue(nControlNode,
								ConfigParameter.CONTROL_ADDBLANKROW);
						if (val.equalsIgnoreCase("Y")) {
							isAddBlankRow = true;
						}
					}
					// find IsChecked
					if (XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_ISCHECKED) != null) {
						String val = XMLPaserUtil.getAttrValue(nControlNode,
								ConfigParameter.CONTROL_ISCHECKED);
						if (val.equalsIgnoreCase("Y")) {
							isChecked = true;
						}
					}
					
					// find IsChecked
					if (XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_OBJ_LOAD_BY_CONFIG) != null) {
						String val = XMLPaserUtil.getAttrValue(nControlNode,
								ConfigParameter.CONTROL_OBJ_LOAD_BY_CONFIG);
						if (val.equalsIgnoreCase("N")) {
							isViewPagerLoadByConfig = false;
						}
					}
					
					// find displayprop
					displayProperty = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_DISPLAYPROP);
					
					// find ValueProp
					valueProperty = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_VALUEPROP);
					// find ContentData
					contentData = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_CONTENTDATA);
					// find rptrDesign
					rptrDesign = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_RPTRDESIGN);
					// find rowItem
					rowItem = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_ROWITEM);
					// find selectWhere
					selectWhere = XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_SELECTWHERE);
					
					mViewpagerHeaderStyle = XMLPaserUtil.getAttrValue(
							nControlNode, ConfigParameter.CONTROL_HEADER_STYLE);
					
					if (XMLPaserUtil.getAttrValue(nControlNode,
							ConfigParameter.CONTROL_CURRENT_PAGE_INDEX) != null) {
						tabhostStartPageIndex = Integer
								.parseInt(XMLPaserUtil
										.getAttrValue(
												nControlNode,
												ConfigParameter.CONTROL_CURRENT_PAGE_INDEX));
					}
					tabhostBackgroundColor = XMLPaserUtil.getAttrValue(
							nControlNode,
							ConfigParameter.CONTROL_BACKGROUND_COLOR);
					
					tabhostDisplayStyle = XMLPaserUtil.getAttrValue(
							nControlNode, ConfigParameter.CONTROL_DISPLAY);
				}
				
				if (nControlNode.getNodeType() == Node.ELEMENT_NODE) {
					Element elementControlNode = (Element) nControlNode;
					// set noblank
					NodeList nodeNonBlank = elementControlNode
							.getElementsByTagName(ConfigParameter.CONTROL_NOBLANK);
					if (nodeNonBlank.getLength() != 0) {
						isNoBlank = true;
					}
					// set ReadOnly
					NodeList nodeReadOnly = elementControlNode
							.getElementsByTagName(ConfigParameter.CONTROL_ISREADONLY);
					if (nodeReadOnly.getLength() != 0) {
						isReadOnly = true;
					}
					// set duplicate
					NodeList nodeDuplicate = elementControlNode
							.getElementsByTagName(ConfigParameter.CONTROL_NODUPLICATE);
					if (nodeDuplicate.getLength() != 0) {
						noDuplicate = true;
					}
					// set validationGroup
					NodeList nodeValidationGroup = elementControlNode
							.getElementsByTagName(ConfigParameter.CONTROL_VALIDATIONGROUP);
					if (nodeValidationGroup.getLength() != 0) {
						validationGroup = XMLPaserUtil
								.getNodeValue(nodeValidationGroup.item(0));
					}
					// find enableWhen tag
					NodeList nodeEnableWhen = elementControlNode
							.getElementsByTagName(ConfigParameter.CONTROL_ENABLEWHEN);
					if (nodeEnableWhen.getLength() != 0) {
						// get firstNode
						Node nEnableWhenNode = nodeEnableWhen.item(0);
						objectBaseRule = setEnableCondition(nEnableWhenNode);
					}
					// find targets tag for ListView
					NodeList nodeTargets = elementControlNode
							.getElementsByTagName(ConfigParameter.CONTROL_TARGETS);
					if (nodeTargets.getLength() != 0) {
						// get firstNode
						Node nTargetsNode = nodeTargets.item(0);
						targetRuleCollection = setTargetsCollection(nTargetsNode);
					}
				}
				
				final ControlType type = controlSpec.getControlType();
				if (type.equals(ControlType.ActionBarMenu)
						|| type.equals(ControlType.ContextMenu)) {
					controlSpec = parseMenuItem(nControlNode);
				} else if (type.equals(ControlType.GridView)) {
					GridViewSpec galleryFormat = parseGalleryFormat(nControlNode);
					galleryFormat.setContentData(contentData);
					galleryFormat.setDataObject(dataObject);
					galleryFormat.setRowItem(rowItem);
					galleryFormat.setRptrdesign(rptrDesign);
					galleryFormat.setTargetRuleCollection(targetRuleCollection);
					controlSpec = galleryFormat;
				} else if (type.equals(ControlType.ViewPager)) {
					ViewPagerSpec pagerFormat = parseViewPagerFormat(nControlNode);
					pagerFormat.setLoadByConfig(isViewPagerLoadByConfig);
					pagerFormat.setHeaderStyle(mViewpagerHeaderStyle);
					controlSpec = pagerFormat;
				} else if (type.equals(ControlType.FragmentTabHost)) {
					TabHostSpec tabHostFormat = parseTabHostFormat(nControlNode);
					tabHostFormat.setBackgroundColor(tabhostBackgroundColor);
					tabHostFormat.setDisplay(tabhostDisplayStyle);
					tabHostFormat.setStartTab(tabhostStartPageIndex);
					controlSpec = tabHostFormat;
				} else if (type.equals(ControlType.EditText)) {
					controlSpec = new EditTextSpec(isNoBlank, isReadOnly,
							isSearch, noDuplicate,
							EditTextType.get(dataInputType), searchControl,
							searchFields, minLength, maxLenght);
				} else if (type.equals(ControlType.ListView)) {
					controlSpec = new ListviewSpec(rowItem, rptrDesign,
							contentData, targetRuleCollection, selectWhere);
				} else if (type.equals(ControlType.Spinner)) {
					SpinnerSpec spinnerSpecFormat = new SpinnerSpec(
							isAddBlankRow, displayProperty, valueProperty,
							contentData, searchControl, searchFields, isSearch);
					controlSpec = spinnerSpecFormat;
				} else if (type.equals(ControlType.Button)) {
					controlSpec = new ButtonSpec(targetRuleCollection);
				} else if (type.equals(ControlType.CheckBox)) {
					controlSpec = new CheckBoxSpec(isChecked);
				}
				
				controlSpec.setControlId(controlId);
				controlSpec.setControlType(controlType);
				controlSpec.setDataObject(dataObject);
				controlSpec.setMappingName(mappingName);
				controlSpec.setValidationGroup(validationGroup);
				controlSpec.setValue(value);
				controlSpec.setVisibility(isVisibility);
				controlSpec.setObjectBaseRule(objectBaseRule);
				controlSpecList.add(controlSpec);
			}
			
		}
		return controlSpecList;
	}
	
	private static GridViewSpec parseGalleryFormat(Node nodeFormat) {
		GridViewSpec galleryFormat = new GridViewSpec();
		Element elementFormat = (Element) nodeFormat;
		NodeList nodeListFormat = elementFormat
				.getElementsByTagName(ConfigParameter.CONTROL_LIST_FORMAT);
		nodeFormat = nodeListFormat.item(0);
		if (nodeFormat.getNodeType() == Node.ELEMENT_NODE) {
			if (nodeFormat.hasAttributes()) {
				String dataObject = XMLPaserUtil.getAttrValue(nodeFormat,
						ConfigParameter.CONTROL_DATAOBJ);
				galleryFormat.setDataObject(dataObject);
			}
			
			elementFormat = (Element) nodeFormat;
			nodeListFormat = elementFormat
					.getElementsByTagName(ConfigParameter.CONTROL_LIST_FORMAT_COLUMN);
			for (int i = 0; i < nodeListFormat.getLength(); i++) {
				Node nodeItem = nodeListFormat.item(i);
				GridViewItem galleryItem = galleryFormat.new GridViewItem();
				if (nodeItem.hasAttributes()) {
					String mappingName = XMLPaserUtil.getAttrValue(nodeItem,
							ConfigParameter.CONTROL_MAPPINGNAME);
					galleryItem.setMappingName(mappingName);
					String dataObject = XMLPaserUtil.getAttrValue(nodeItem,
							ConfigParameter.CONTROL_DATAOBJ);
					galleryItem.setDataObject(dataObject);
					
					galleryFormat.add(galleryItem);
				}
			}
			
			nodeListFormat = elementFormat
					.getElementsByTagName(ConfigParameter.CONTROL_FILTER);
			Node nodeFiler = nodeListFormat.item(0);
			if (nodeFiler.hasAttributes()) {
				ObjectFilter filter = new ObjectFilter();
				String mappingName = XMLPaserUtil.getAttrValue(nodeFiler,
						ConfigParameter.CONTROL_MAPPINGNAME);
				filter.setMappingName(mappingName);
				String dataObject = XMLPaserUtil.getAttrValue(nodeFiler,
						ConfigParameter.CONTROL_DATAOBJ);
				filter.setDataObject(dataObject);
				String defaultValue = XMLPaserUtil.getAttrValue(nodeFiler,
						ConfigParameter.CONTROL_DEFAULT_VALUE);
				filter.setDefaultValue(defaultValue);
				galleryFormat.setFilter(filter);
			}
		}
		return galleryFormat;
	}
	
	private static PopupMenuSpec parsePopupMenuFormat(Node nodeFormat) {
		Element elementFormat = (Element) nodeFormat;
		if (elementFormat.hasChildNodes()) {
			PopupMenuSpec popupMenuFormat = new PopupMenuSpec();
			NodeList nodeListFormat = elementFormat
					.getElementsByTagName(ConfigParameter.CONTROL_POPUP_MENU);
			nodeFormat = nodeListFormat.item(0);
			if (nodeFormat.getNodeType() == Node.ELEMENT_NODE) {
				elementFormat = (Element) nodeFormat;
				nodeListFormat = elementFormat
						.getElementsByTagName(ConfigParameter.CONTROL_SUB_MENU);
				for (int i = 0; i < nodeListFormat.getLength(); i++) {
					Node nodeItem = nodeListFormat.item(i);
					PopupMenuItem popupMenuItem = popupMenuFormat.new PopupMenuItem();
					if (nodeItem.hasAttributes()) {
						String title = XMLPaserUtil.getAttrValue(nodeItem,
								ConfigParameter.CONTROL_TITLE);
						popupMenuItem.setTitle(title);
						String className = XMLPaserUtil.getAttrValue(nodeItem,
								ConfigParameter.CONTROL_CLASS);
						popupMenuItem.setClassName(className);
						popupMenuFormat.add(popupMenuItem);
					}
				}
			}
			return popupMenuFormat;
		}
		return null;
	}
	
	private static TabHostSpec parseTabHostFormat(Node nodeFormat) {
		TabHostSpec tabHostSpecFormat = new TabHostSpec();
		Element elementFormat = (Element) nodeFormat;
		NodeList nodeListFormat = elementFormat
				.getElementsByTagName(ConfigParameter.CONTROL_TABHOST_MENU);
		nodeFormat = nodeListFormat.item(0);
		if (nodeFormat.getNodeType() == Node.ELEMENT_NODE) {
			elementFormat = (Element) nodeFormat;
			nodeListFormat = elementFormat
					.getElementsByTagName(ConfigParameter.CONTROL_MENU);
			for (int i = 0; i < nodeListFormat.getLength(); i++) {
				Node nodeItem = nodeListFormat.item(i);
				TabItem tabItem = tabHostSpecFormat.new TabItem();
				if (nodeItem.hasAttributes()) {
					// Get pager Class
					String pagerItemClass = XMLPaserUtil.getAttrValue(nodeItem,
							ConfigParameter.CONTROL_CLASS);
					tabItem.setPagerItemClass(pagerItemClass);
					// Get pager title
					String title = XMLPaserUtil.getAttrValue(nodeItem,
							ConfigParameter.CONTROL_TITLE);
					tabItem.setTitle(title);
					// Get pager icon
					String icon = XMLPaserUtil.getAttrValue(nodeItem,
							ConfigParameter.CONTROL_ICON);
					tabItem.setIcon(icon);
					// Get tag
					String tag = XMLPaserUtil.getAttrValue(nodeItem,
							ConfigParameter.CONTROL_TAG);
					tabItem.setTag(tag);
				}
				PopupMenuSpec popupMenuFormat = parsePopupMenuFormat(nodeItem);
				tabItem.setPopupMenuFormat(popupMenuFormat);
				tabHostSpecFormat.add(tabItem);
			}
		}
		return tabHostSpecFormat;
	}
	
	private static ViewPagerSpec parseViewPagerFormat(Node nodeFormat) {
		ViewPagerSpec galleryFormat = new ViewPagerSpec();
		Element elementFormat = (Element) nodeFormat;
		NodeList nodeListFormat = elementFormat
				.getElementsByTagName(ConfigParameter.CONTROL_TARGETS);
		nodeFormat = nodeListFormat.item(0);
		if (nodeFormat.getNodeType() == Node.ELEMENT_NODE) {
			if (nodeFormat.hasAttributes()) {
				String defaultTarget = XMLPaserUtil.getAttrValue(nodeFormat,
						ConfigParameter.CONTROL_TARGETS_DEFAULT_TARGET);
				galleryFormat.setDefaultTarget(defaultTarget);
			}
			elementFormat = (Element) nodeFormat;
			nodeListFormat = elementFormat
					.getElementsByTagName(ConfigParameter.CONTROL_TARGET);
			for (int i = 0; i < nodeListFormat.getLength(); i++) {
				Node nodeItem = nodeListFormat.item(i);
				ViewPagerItem galleryItem = galleryFormat.new ViewPagerItem();
				if (nodeItem.hasAttributes()) {
					// Get pager Class
					String pagerItemClass = XMLPaserUtil.getAttrValue(nodeItem,
							ConfigParameter.CONTROL_CLASS);
					galleryItem.setPagerItemClass(pagerItemClass);
					// Get pager title
					String title = XMLPaserUtil.getAttrValue(nodeItem,
							ConfigParameter.CONTROL_TITLE);
					galleryItem.setTitle(title);
					// Get pager icon
					String icon = XMLPaserUtil.getAttrValue(nodeItem,
							ConfigParameter.CONTROL_ICON);
					galleryItem.setIcon(icon);
				}
				galleryFormat.add(galleryItem);
			}
		}
		return galleryFormat;
	}
	
	private static MenuSpec parseMenuItem(Node menuElementNode) {
		MenuSpec customMenu = new MenuSpec();
		
		Element menuNode = (Element) menuElementNode;
		NodeList listMenu = menuNode
				.getElementsByTagName(ConfigParameter.CONTROL_MENU);
		Node menuItem = listMenu.item(0);
		if (menuItem.getNodeType() == Node.ELEMENT_NODE) {
			Element elementMenuItem = (Element) menuItem;
			NodeList listMenuItem = elementMenuItem
					.getElementsByTagName(ConfigParameter.CONTROL_SUB_MENU);
			for (int i = 0; i < listMenuItem.getLength(); i++) {
				Node nodeMenuItem = listMenuItem.item(i);
				if (nodeMenuItem.hasAttributes()) {
					Attr attr = (Attr) nodeMenuItem.getAttributes()
							.getNamedItem(ConfigParameter.CONTROL_ID);
					
					MenuSpec.MenuItem item = customMenu.new MenuItem();
					if (attr != null) {
						String icon = attr.getNodeValue();
						item.setId(icon);
					}
					
					// set validationGroup
					NodeList nodeValidationGroup = ((Element) nodeMenuItem)
							.getElementsByTagName(ConfigParameter.CONTROL_VALIDATIONGROUP);
					if (nodeValidationGroup.getLength() != 0) {
						String groupName = XMLPaserUtil
								.getNodeValue(nodeValidationGroup.item(0));
						item.setValidationgroup(groupName);
					}
					customMenu.add(item);
				}
			}
		}
		return customMenu;
	}
	
	private static ObjectBaseRule setEnableCondition(Node nEnableWhenNode) {
		
		ObjectBaseRule objectBaseRule = null;
		
		if (nEnableWhenNode.getNodeType() == Node.ELEMENT_NODE) {
			Element element = (Element) nEnableWhenNode;
			
			// get data_rules Node
			NodeList dataRuleNodes = element
					.getElementsByTagName(ConfigParameter.CONTROL_ENABLEWHEN_DATA_RULES);
			if (dataRuleNodes.getLength() == 0) {
				return null;
			}
			Node nDataRuleNode = dataRuleNodes.item(0);
			
			if (nDataRuleNode.getNodeType() == Node.ELEMENT_NODE) {
				
				Element dataRuleElement = (Element) nDataRuleNode;
				
				// get <objloaded/> -- <objnotloaded/> -- <maxrec>
				
				// find objloaded tagname
				NodeList nodeObjLoaded = dataRuleElement
						.getElementsByTagName(ConfigParameter.CONTROL_ENABLEWHEN_DATA_RULES_OBJLOADED);
				if (nodeObjLoaded.getLength() != 0) {
					
					// we initiate ActionBaseRule for this Object (like
					// <comparevalue/> or etc)
					ActionBaseRule actionBaseRule = null;
					
					NodeList nodeCompareValue = dataRuleElement
							.getElementsByTagName(ConfigParameter.CONTROL_ENABLEWHEN_DATA_RULES_COMPAREVALUE);
					if (nodeCompareValue.getLength() != 0) {
						
						// we get NodeList rules_prop
						NodeList nodeRuleProp = dataRuleElement
								.getElementsByTagName(ConfigParameter.CONTROL_ENABLEWHEN_DATA_RULES_PROP);
						if (nodeRuleProp.getLength() != 0) {
							Node nNodeRuleProp = nodeRuleProp.item(0);
							
							if (nNodeRuleProp.getNodeType() == Node.ELEMENT_NODE) {
								
								Element dataRulePropElement = (Element) nNodeRuleProp;
								
								// we get <prop> tag of this node
								NodeList nodeProp = dataRulePropElement
										.getElementsByTagName(ConfigParameter.CONTROL_ENABLEWHEN_DATA_RULES_PROPDETAIL);
								if (nodeProp.getLength() != 0) {
									
									Node nNodeProp = nodeProp.item(0);
									// we convert this node into element
									Element nodePropElement = (Element) nNodeProp;
									
									// HERE, we get whole <obj_prop> tags of
									// this Node
									NodeList objPropNodeList = nodePropElement
											.getElementsByTagName(ConfigParameter.CONTROL_ENABLEWHEN_DATA_RULES_PROPDETAIL_OBJPROP);
									
									// WE CREATE ActionBaseRule for this Object
									// is <comparevalue/>
									ArrayList<ObjPropInfo> arrObjPropInfo = new ArrayList<ObjPropInfo>();
									
									for (int temp = 0; temp < objPropNodeList
											.getLength(); temp++) {
										Node nObjPropNode = objPropNodeList
												.item(temp);
										
										if (nObjPropNode.getNodeType() == Node.ELEMENT_NODE) {
											
											ObjPropInfo objPropInfo = new ObjPropInfo();
											String content;
											Element elementObjPropNode = (Element) nObjPropNode;
											
											// get Object_ID of this property
											NodeList objPropIDNodes = elementObjPropNode
													.getElementsByTagName(ConfigParameter.OBJ_CLASS_ID);
											if (objPropIDNodes.getLength() != 0) {
												content = XMLPaserUtil
														.getNodeValue(objPropIDNodes
																.item(0));
												objPropInfo
														.setObjectMapping(content);
											}
											
											// get Attribute_ID of this property
											NodeList objPropAttributeIDNodes = elementObjPropNode
													.getElementsByTagName(ConfigParameter.OBJ_PROP_ID);
											if (objPropAttributeIDNodes
													.getLength() != 0) {
												content = XMLPaserUtil
														.getNodeValue(objPropAttributeIDNodes
																.item(0));
												objPropInfo
														.setObjectProperty(content);
											}
											
											// get data_type of this property
											NodeList objPropDataTypeNodes = elementObjPropNode
													.getElementsByTagName(ConfigParameter.OBJ_PROP_DATATYPE);
											if (objPropDataTypeNodes
													.getLength() != 0) {
												content = XMLPaserUtil
														.getNodeValue(objPropDataTypeNodes
																.item(0));
												objPropInfo
														.setDataType(content);
											}
											
											// get filter node of this property
											NodeList objPropFilterNodes = elementObjPropNode
													.getElementsByTagName(ConfigParameter.OBJ_PROP_FILTER);
											if (objPropFilterNodes.getLength() != 0) {
												
												// we get the first Filter Node
												Node objPropFilterNode = objPropFilterNodes
														.item(0);
												
												// we get attribute operator and
												// value of this node
												if (objPropFilterNode
														.hasAttributes()) {
													
													ValueBaseRule valueBaseRule = null;
													String operator = "";
													String value1 = "";
													
													// find attr operator
													Attr attr = (Attr) objPropFilterNode
															.getAttributes()
															.getNamedItem(
																	ConfigParameter.OBJ_PROP_FILTER_OPERATOR);
													if (attr != null) {
														operator = attr
																.getNodeValue();
													}
													
													// find attr operator
													attr = (Attr) objPropFilterNode
															.getAttributes()
															.getNamedItem(
																	ConfigParameter.OBJ_PROP_FILTER_VALUE1);
													if (attr != null) {
														value1 = attr
																.getNodeValue();
													}
													
													// we find appropriate
													// ValueBaseRule for this
													// ObjPropInfo based on
													// operator, value1
													if (operator
															.compareToIgnoreCase(ConfigParameter.CONTROL_ENABLEWHEN_DATA_RULES_PROPDETAIL_FILTER_OPERATOR_EQUAL) == 0) {
														valueBaseRule = new ValueEqualRule(
																value1);
													} else if (operator
															.compareToIgnoreCase(ConfigParameter.CONTROL_ENABLEWHEN_DATA_RULES_PROPDETAIL_FILTER_OPERATOR_CONTAIN) == 0) {
														valueBaseRule = new ValueContainRule(
																value1);
													}
													
													objPropInfo.valueBaseRule = valueBaseRule;
												}
											}
											
											arrObjPropInfo.add(objPropInfo);
										}
									}
									
									// set for arrObjPropInfo
									actionBaseRule = new ActionCompareRule(
											arrObjPropInfo);
								}
							}
						}
					}
					
					// Eventually, it means we can create ObjectBaseRule as
					// ObjectLoadBaseRule by an ActionBaseRule
					objectBaseRule = new ObjectLoadBaseRule(actionBaseRule);
					
				}
				
				// find objnotloaded tagname
				NodeList nodeObjNotLoaded = dataRuleElement
						.getElementsByTagName(ConfigParameter.CONTROL_ENABLEWHEN_DATA_RULES_OBJNOTLOADED);
				if (nodeObjNotLoaded.getLength() != 0) {
					// it means we can create ObjectBaseRule as
					// ObjectNotLoadBaseRule
					objectBaseRule = new ObjectNotLoadBaseRule();
				}
				
				// find maxrec tagname
				NodeList nodeMaxRec = dataRuleElement
						.getElementsByTagName(ConfigParameter.CONTROL_ENABLEWHEN_DATA_RULES_MAXREC);
				if (nodeMaxRec.getLength() != 0) {
					// it means we can create ObjectBaseRule as MaxRec
					
				}
				
			}
		}
		
		return objectBaseRule;
	}
	
	private static TargetRuleCollection setTargetsCollection(Node nTargetsNode) {
		TargetRuleCollection targetRuleCollection = null;
		
		if (nTargetsNode.hasAttributes()) {
			
			// find attr defaultTarget
			Attr attr = (Attr) nTargetsNode.getAttributes().getNamedItem(
					ConfigParameter.CONTROL_TARGETS_DEFAULT_TARGET);
			if (attr != null) {
				targetRuleCollection = new TargetRuleCollection();
				
				String defaultTarget = attr.getNodeValue();
				targetRuleCollection.setDefaultTarget(defaultTarget);
			}
		}
		
		if (targetRuleCollection != null) {
			if (nTargetsNode.getNodeType() == Node.ELEMENT_NODE) {
				
				Element dataTargetRuleElement = (Element) nTargetsNode;
				// and then fetch specific targets based on the value of
				// GenericObject
				
				// we get <rules_prop> tag of this node
				NodeList nodePropList = dataTargetRuleElement
						.getElementsByTagName(ConfigParameter.CONTROL_TARGETS_LISTVIEW_RULES_PROPS);
				if (nodePropList.getLength() != 0) {
					
					ArrayList<TargetRule> targetList = new ArrayList<TargetRule>();
					
					for (int temp = 0; temp < nodePropList.getLength(); temp++) {
						Node targetNode = nodePropList.item(temp);
						
						TargetRule targetRule = new TargetRule();
						ActionCompareRule actionCompareRule = null;
						// set Target for this Rule
						if (targetNode.hasAttributes()) {
							
							// find attr target
							Attr attr = (Attr) targetNode.getAttributes()
									.getNamedItem(
											ConfigParameter.CONTROL_TARGET);
							if (attr != null) {
								
								String targetActivity = attr.getNodeValue();
								if (targetActivity.compareTo("") == 0) {
									// we set default target activity for this
									// target
									targetRule
											.setTargetActivity(targetRuleCollection
													.getDefaultTarget());
								} else {
									targetRule
											.setTargetActivity(targetActivity);
								}
							}
						}
						
						// we fetch obj_prop for this target
						if (targetNode.getNodeType() == Node.ELEMENT_NODE) {
							// we set TargetRule by ObjPropInfo, we create list
							// of ObjPropInfo
							Element targetNodeElement = (Element) targetNode;
							
							// we get <prop> tag of this node
							NodeList nodeProp = targetNodeElement
									.getElementsByTagName(ConfigParameter.CONTROL_TARGETS_LISTVIEW_RULES_PROPS_PROP);
							if (nodeProp.getLength() != 0) {
								
								Node nNodeProp = nodeProp.item(0);
								// we convert this node into element
								Element nodePropElement = (Element) nNodeProp;
								
								// HERE, we get whole <obj_prop> tags of this
								// Node
								NodeList objPropNodeList = nodePropElement
										.getElementsByTagName(ConfigParameter.CONTROL_TARGETS_LISTVIEW_RULES_PROPS_PROP_OBJPROP);
								
								ArrayList<ObjPropInfo> arrObjPropInfo = new ArrayList<ObjPropInfo>();
								
								for (int objpropIndex = 0; objpropIndex < objPropNodeList
										.getLength(); objpropIndex++) {
									Node nObjPropNode = objPropNodeList
											.item(objpropIndex);
									
									if (nObjPropNode.getNodeType() == Node.ELEMENT_NODE) {
										
										ObjPropInfo objPropInfo = new ObjPropInfo();
										String content;
										Element elementObjPropNode = (Element) nObjPropNode;
										
										// get Object_ID of this property
										NodeList objPropIDNodes = elementObjPropNode
												.getElementsByTagName(ConfigParameter.OBJ_CLASS_ID);
										if (objPropIDNodes.getLength() != 0) {
											content = XMLPaserUtil
													.getNodeValue(objPropIDNodes
															.item(0));
											objPropInfo
													.setObjectMapping(content);
										}
										
										// get Attribute_ID of this property
										NodeList objPropAttributeIDNodes = elementObjPropNode
												.getElementsByTagName(ConfigParameter.OBJ_PROP_ID);
										if (objPropAttributeIDNodes.getLength() != 0) {
											content = XMLPaserUtil
													.getNodeValue(objPropAttributeIDNodes
															.item(0));
											objPropInfo
													.setObjectProperty(content);
										}
										
										// get data_type of this property
										NodeList objPropDataTypeNodes = elementObjPropNode
												.getElementsByTagName(ConfigParameter.OBJ_PROP_DATATYPE);
										if (objPropDataTypeNodes.getLength() != 0) {
											content = XMLPaserUtil
													.getNodeValue(objPropDataTypeNodes
															.item(0));
											objPropInfo.setDataType(content);
										}
										
										// get filter node of this property
										NodeList objPropFilterNodes = elementObjPropNode
												.getElementsByTagName(ConfigParameter.OBJ_PROP_FILTER);
										if (objPropFilterNodes.getLength() != 0) {
											
											// we get the first Filter Node
											Node objPropFilterNode = objPropFilterNodes
													.item(0);
											
											// we get attribute operator and
											// value of this node
											if (objPropFilterNode
													.hasAttributes()) {
												
												ValueBaseRule valueBaseRule = null;
												String operator = "";
												String value1 = "";
												
												// find attr operator
												Attr attr = (Attr) objPropFilterNode
														.getAttributes()
														.getNamedItem(
																ConfigParameter.OBJ_PROP_FILTER_OPERATOR);
												if (attr != null) {
													operator = attr
															.getNodeValue();
												}
												
												// find attr operator
												attr = (Attr) objPropFilterNode
														.getAttributes()
														.getNamedItem(
																ConfigParameter.OBJ_PROP_FILTER_VALUE1);
												if (attr != null) {
													value1 = attr
															.getNodeValue();
												}
												
												// we find appropriate
												// ValueBaseRule for this
												// ObjPropInfo based on
												// operator, value1
												if (operator
														.compareToIgnoreCase(ConfigParameter.CONTROL_ENABLEWHEN_DATA_RULES_PROPDETAIL_FILTER_OPERATOR_EQUAL) == 0) {
													valueBaseRule = new ValueEqualRule(
															value1);
												} else if (operator
														.compareToIgnoreCase(ConfigParameter.CONTROL_ENABLEWHEN_DATA_RULES_PROPDETAIL_FILTER_OPERATOR_CONTAIN) == 0) {
													valueBaseRule = new ValueContainRule(
															value1);
												}
												
												objPropInfo.valueBaseRule = valueBaseRule;
											}
										}
										
										arrObjPropInfo.add(objPropInfo);
									}
									
								}
								// we set arrObjPropInfo for this TargetRule
								actionCompareRule = new ActionCompareRule(
										arrObjPropInfo);
							}
							
							// it must be ActioNCompareRule
							targetRule.setActionBaseRule(actionCompareRule);
						}
						
						// add currentTarget into TargetList
						targetList.add(targetRule);
					}
					
					// set TargetList for current Rule Collection
					targetRuleCollection.setArrTargetRules(targetList);
				}
			}
		}
		
		return targetRuleCollection;
	}
	
	public static ArrayList<ControlSpec> parserIntoControls(
			Context paramContext, int xmlfileId, String tagname) {
		try {
			Document doc = XMLPaserUtil.openDocumentFrom(paramContext,
					xmlfileId);
			return parse(doc, tagname);
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Resources.NotFoundException e) {
			e.printStackTrace();
		}
		return new ArrayList<ControlSpec>();
	}
	
	public static ArrayList<ControlSpec> parserIntoControls(
			Context paramContext, String xmlfilename, String tagname) {
		Document doc;
		try {
			doc = XMLPaserUtil.openDocumentFrom(paramContext, xmlfilename);
			return parse(doc, tagname);
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
}
